<!DOCTYPE html>

<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0"/>
    <title>守卫OAuth 2.1</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            margin: 0;
            padding: 20px;
        }

        #app {
            max-width: 600px;
            margin: 0 auto;
        }

        .section {
            margin-bottom: 20px;
            padding: 20px;
            border: 1px solid #ccc;
            border-radius: 5px;
            background-color: #f9f9f9;
        }

        .section p {
            margin-bottom: 10px;
            color: red;
        }

        form {
            margin-top: 10px;
        }

        label {
            display: inline-block;
            width: 120px;
            margin-bottom: 10px;
        }

        input[type="text"],
        input[type="password"],
        input[type="file"] {
            padding: 5px;
            margin-bottom: 10px;
            border: 1px solid #ccc;
            border-radius: 3px;
            width: 200px;
        }

        button {
            padding: 7px;
            background-color: #4CAF50;
            color: white;
            border: none;
            border-radius: 3px;
            cursor: pointer;
            width: 100px;
            /* 防止字体超出 */
            white-space: nowrap;
            overflow: hidden;
            text-overflow: ellipsis;
        }

        button:hover {
            background-color: #45a049;
        }

        #avatarPreview {
            margin-top: 10px;
        }

        table {
            border-collapse: collapse;
            width: 100%;
        }

        th, td {
            border: 1px solid #ddd;
            padding: 8px;
            text-align: left;
        }

        th {
            background-color: #f2f2f2;
        }

        tr:nth-child(even) {
            background-color: #f9f9f9;
        }

        p {
            color: #258c1e;
        }

        .input-hint {
            font-size: 12px;
            color: #999;
        }

        /* 媒体查询 */

        @media screen and (max-width: 600px) {
            body {
                padding: 10px;
            }

            .section {
                padding: 10px;
            }

            input[type="text"],
            input[type="password"],
            input[type="file"] {
                width: 100%;
            }

            button {
                width: 100%;
            }
        }
    </style>
</head>
<body>
<div id="app">
    <div id="user" class="section">
        <div style="margin-bottom: 10px">
            用户：{{ .username}}
            <a style="margin-left: 15px" href="/logout">注销</a>
        </div>
        <div style="margin-bottom: 10px">
            <p style="color:red">{{.error}}</p>
        </div>

        <!-- 使用javascript做的渲染 -->
        <div>
            <table id="client_table"></table>
        </div>

        <div style="display: flex;justify-content: space-between;margin-top: 5px">
            <button onclick="toggleSection('userInfo')">修改用户信息</button>
            <button onclick="toggleSection('userPassword')">修改用户密码</button>
            <button onclick="toggleSection('registerClient')">申请客户端</button>
            <button onclick="applyClient()">我的客户端</button>
        </div>
    </div>
    <div id="userInfo" class="section" style="display: none">
        <label for="new_nickname">昵称：</label>
        <input type="text" name="new_nickname" id="new_nickname" required/><br>
        <!-- 头像模块 -->
        <label for="new_avatar">头像：</label>
        <input type="file" id="new_avatar" accept="image/*"/><br>
        <button id="submit_userinfo">修改</button>
        <div id="avatarPreview"></div>
    </div>
    <div id="userPassword" class="section" style="display: none">
        <label for="old_password">旧密码：</label>
        <input type="password" name="old_password" id="old_password" required/><br>
        <label for="new_password">新密码：</label>
        <input type="password" name="new_password" id="new_password" required/><br>
        <label for="new_ok_password">确定新密码：</label>
        <input type="password" id="new_ok_password" required/><br>
        <button id="submit_password_button" onclick="submitUserPassword()">修改</button>
    </div>
    <div id="registerClient" class="section" style="display: none">
        <div style="display: none">
            <label for="client_id"></label>
            <input type="text" name="client_id" id="client_id"/><br>
        </div>
        <div>
            <label for="client_name">App名称：</label>
            <input type="text" name="client_name" id="client_name" required/><br>
            <span class="input-hint">App名称需要大于6个字符</span>
        </div>
        <div>
            <label for="redirect_uris">重定向URI：</label>
            <input type="text" name="redirect_uris" id="redirect_uris" required/><br>
            <span class="input-hint">确定要返回授权码的url，使用,号分割更多uri。</span>
        </div>
        <button onclick="submitRegisterClient()">提交</button>
        <div>
            <h6>需要设置授权码过期时间，Token过期时间，RefreshToken过期时间需要联系管理员</h6>
        </div>
    </div>
</div>
<script>
    // 头像相关
    const fileInput = document.getElementById('new_avatar');
    let base64String = null; // 存储Base64编码的字符串

    fileInput.addEventListener('change', () => {
        const file = fileInput.files[0];
        const maxSizeInBytes = 100 * 1024; // 100KB

        // 清除previewContainer中的内容
        document.getElementById('avatarPreview').innerHTML = "";

        if (file && file.size <= maxSizeInBytes) {
            // 显示头像
            const previewImage = document.createElement('img');
            previewImage.src = URL.createObjectURL(file);
            const avatarPreview = document.getElementById('avatarPreview');
            avatarPreview.appendChild(previewImage);

            // 读取图片
            const reader = new FileReader();
            reader.onload = (event) => {
                base64String = event.target.result.split(",")[1]; // 获取Base64编码的字符串
            };
            reader.readAsDataURL(file);
        } else {
            // 文件大小超过限制的处理逻辑
            showCustomAlert('文件大小超过限制，请选择小于100KB的文件。');
            fileInput.value = ''; // 清空文件输入框的值
        }

        if (fileInput.files.length > 1) {
            showCustomAlert('只能选择一个头像文件，请重新选择。');
            fileInput.value = ''; // 清空文件输入框的值
        }
    });

    // 提交按钮的点击事件处理程序
    document.getElementById('submit_userinfo').addEventListener('click', () => {
        if (base64String) {
            // 将base64的图片，放到表单里，直接fetch方式提交，不需要放表单里
            // document.getElementById('picture').value = base64String
            // 提交信息
            const mui = {
                new_nickname: document.getElementById("new_nickname").value,
                new_picture: base64String
            }
            fetch("modify_user_userinfo", {
                method: "POST",
                headers: {
                    'Content-Type': 'application/json'
                },
                body: JSON.stringify(mui)
            })
                .then(response => response.json())
                .then(data => {
                    showCustomAlert(data.msg)
                })
        } else {
            showCustomAlert('请先选择头像文件。');
        }
    });

    // 切换用，需要在div上设置style="display: none"，不然会有延时，用css，第一时间获取的是空的
    function toggleSection(sectionId) {
        if (sectionId === "registerClient") {
            // 重置客户端申请框
            document.getElementsByName("client_id")[0].value = ""
            document.getElementsByName("client_name")[0].value = ""
            rudg = document.getElementsByName("redirect_uris")[0]
            rudg.value = ""
            rudg.placeholder = ""
        }
        const section = document.getElementById(sectionId);
        section.style.display = section.style.display === 'none' ? 'block' : 'none';
    }

    // 修改密码
    function submitUserPassword() {
        let old_Pwd = document.getElementById("old_password").value
        let new_pwd = document.getElementById("new_password").value
        let new_pwd_ok = document.getElementById("new_ok_password").value
        if (old_Pwd === "" || new_pwd === "" || new_pwd !== new_pwd_ok) {
            // 添加一个提示信息
            showCustomAlert("新密码和确认密码不一致，请重新输入！");
            return false;
        } else {
            // 提交信息
            const mup = {
                old_password: old_Pwd,
                new_password: new_pwd
            }
            fetch("modify_user_password", {
                method: "POST",
                headers: {
                    'Content-Type': 'application/json'
                },
                body: JSON.stringify(mup)
            })
                .then(response => response.json())
                .then(data => {
                    showCustomAlert(data.msg + "，请刷新当前页面，并重新登录")
                })
        }
    }

    // 注册客户端
    function submitRegisterClient() {
        let clientId = document.getElementById("client_id").value
        let clientName = document.getElementById("client_name").value
        let r_uris = document.getElementById("redirect_uris").value
        if (clientName === "" || r_uris === "") {
            showCustomAlert("请输入完整的客户端信息")
            return false
        } else {
            const cr = {
                client_id: clientId,
                client_name: clientName,
                redirect_uris: r_uris
            }
            fetch("register_client", {
                method: "POST",
                headers: {
                    'Content-Type': 'application/json'
                },
                body: JSON.stringify(cr)
            })
                .then(response => response.json())
                .then(data => {
                    if (data.code === 200) {
                        applyClient()
                    }
                    showCustomAlert(data.msg)
                })
        }
    }

    // 查询客户端，删除客户端
    function applyClient() {
        // 获取表格元素
        const table = document.getElementById('client_table');
        // 重置表格
        table.innerHTML = ""
        // 创建表头行
        const headerRow = table.insertRow();
        // 创建表头单元格
        const appNameHeader = document.createElement("th");
        appNameHeader.innerHTML = "应用名称";
        headerRow.appendChild(appNameHeader);

        const clientIdHeader = document.createElement("th");
        clientIdHeader.innerHTML = "客户端Key";
        headerRow.appendChild(clientIdHeader);

        const clientSecretHeader = document.createElement("th");
        clientSecretHeader.innerHTML = "客户端Secret";
        headerRow.appendChild(clientSecretHeader);

        const actionHeader = document.createElement("th");
        actionHeader.innerHTML = "操作";
        headerRow.appendChild(actionHeader);

        fetch("apply_client")
            .then(response => response.json())
            .then(data => {
                // 使用forEach迭代集合数据
                data.data.forEach(function (item) {
                    // 创建新行
                    const row = table.insertRow();

                    // 创建单元格
                    const appNameCell = row.insertCell();
                    const clientIdCell = row.insertCell();
                    const clientSecretCell = row.insertCell();
                    const actionCell = row.insertCell();

                    // 设置单元格内容，添加指定的数据
                    appNameCell.innerHTML = item.client_name;
                    clientIdCell.innerHTML = item.client_id; // 使用实际的数据值
                    clientSecretCell.innerHTML = item.client_secret; // 使用实际的数据值

                    // 生成删除链接
                    const deleteLink = document.createElement("a");
                    deleteLink.href = "javascript:;";               // href变为javascript:;，让其url不跳转到#
                    deleteLink.innerHTML = "删除";
                    // 将client_id作为自定义属性添加到删除链接上
                    // deleteLink.setAttribute("data-client-id", item.client_id);
                    deleteLink.addEventListener("click", function () {          // 给a标签绑定个事件
                        if (confirm("是否要删除这个client呢，删除后将无法恢复")) {
                            // const clientId = this.getAttribute("data-client-id"); // 获取自定义属性值
                            const clientId = item.client_id
                            fetch("del_app", {
                                method: "POST",
                                headers: {
                                    "Content-Type": "application/json"
                                },
                                body: JSON.stringify({client_id: clientId})
                            })
                                .then(response => response.json())
                                .then(data => {
                                    if (data.code === 200) {
                                        table.deleteRow(row.rowIndex);
                                    }
                                    showCustomAlert(data.msg)
                                })
                        }
                    });
                    // 生成修改按钮
                    const modifyLink = document.createElement("a")
                    modifyLink.href = "javascript:;";
                    modifyLink.innerHTML = "修改"
                    modifyLink.addEventListener("click", function () {
                        const cid = item.client_id
                        const cname = item.client_name

                        toggleSection("registerClient")
                        document.getElementsByName("client_id")[0].value = cid
                        document.getElementsByName("client_name")[0].value = cname
                        ru_tig = document.getElementsByName("redirect_uris")[0]
                        ru_tig.placeholder = "请输入新的重定向地址"
                    })
                    actionCell.appendChild(modifyLink)
                    actionCell.appendChild(deleteLink);
                });
            })
    }
</script>
</body>
</html>
<!-- 美化alert，不用第三方 -->
<style>
    .custom-alert {
        display: none;
        position: fixed;
        top: 50%;
        left: 50%;
        transform: translate(-50%, -50%);
        background-color: #fff;
        border: 1px solid #ccc;
        padding: 10px 20px;
        border-radius: 5px;
        box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
        z-index: 9999;
    }

    .custom-alert-message {
        display: block;
        font-size: 16px;
        color: #333;
        margin-bottom: 10px;
    }
</style>
<div id="customAlert" class="custom-alert">
    <span id="customAlertMessage" class="custom-alert-message"></span>
</div>
<script>
    function showCustomAlert(message) {
        // 创建提示框元素
        const alertContainer = document.getElementById("customAlert");
        const alertMessage = document.getElementById("customAlertMessage");

        // 设置提示信息内容
        alertMessage.innerHTML = message;

        // 显示提示框
        alertContainer.style.display = "block";

        // 3秒后隐藏提示框
        setTimeout(function () {
            alertContainer.style.display = "none";
        }, 2000);
    }
</script>